package zsd.reiview.experiment.crf;

import java.awt.geom.Path2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import org.apache.log4j.Logger;

import zsd.reiview.experiment.crf.CrfCorpus.COAE2009TargetCorpus;
import zsd.reiview.experiment.crf.CrfCorpus.Task3Corpus;
import zsd.reiview.utility.FileUtility;
import zsd.reiview.utility.StringUtility;
import zsd.review.common.Option;

import com.aliasi.chunk.BioTagChunkCodec;
import com.aliasi.chunk.Chunker;
import com.aliasi.chunk.ChunkerEvaluator;
import com.aliasi.chunk.Chunking;
import com.aliasi.chunk.ChunkingEvaluation;
import com.aliasi.chunk.TagChunkCodec;
import com.aliasi.classify.PrecisionRecallEvaluation;
import com.aliasi.corpus.ListCorpus;
import com.aliasi.corpus.ObjectHandler;
import com.aliasi.corpus.XValidatingObjectCorpus;
import com.aliasi.crf.ChainCrf;
import com.aliasi.crf.ChainCrfChunker;
import com.aliasi.crf.ChainCrfFeatureExtractor;
import com.aliasi.io.LogLevel;
import com.aliasi.io.Reporter;
import com.aliasi.io.Reporters;
import com.aliasi.stats.AnnealingSchedule;
import com.aliasi.stats.RegressionPrior;
import com.aliasi.tag.Tagging;
import com.aliasi.tokenizer.CharacterTokenizerFactory;
import com.aliasi.tokenizer.TokenNGramTokenizerFactory;
import com.aliasi.tokenizer.TokenizerFactory;
import com.aliasi.util.AbstractExternalizable;
import com.aliasi.util.Arrays;

/**
 * @Title: CrfChunker.java
 * @Package zsd.reiview.experiment.crf
 * @Description: TODO(添加描述)
 * @author 朱圣代
 * @date 2011-10-31 下午02:34:43
 * @version V1.0
 */
public class CrfChunkerTest {

	/**
	 * @Title: main
	 * @Description:
	 * @param @param args
	 * @return void
	 * @throws
	 * @date 2011-10-31 下午02:34:43
	 */

	private static final Logger log = Logger.getLogger(CrfChunkerTest.class);

	int NUM_FOLDS = 10;

	public TokenizerFactory tokenizerFactory;
	TokenizerFactory trainFactory;

	public String[] getPath(String dir, String name,int num) throws IOException {
		String[] paths = new String[num];
		for (int i = 0; i < num; i++) {
			paths[i] = dir + File.separator + name + "_" + i + ".txt";
			FileUtility.createFile(paths[i]);
		}
		return paths;
	}

	public final String dir = "myDataBase" + File.separator + "models" + File.separator;

	/**
	 * @Title: main
	 * @Description:
	 * @param @param args
	 * @return void
	 * @throws Exception
	 * @throws
	 * @date 2011-10-7 下午07:35:54
	 */

	// 在11上选定领域做交叉验证
	public Result testIsTrain(int tokeFac, String cat, String name, int from, int to, boolean tran, boolean tagTarget, boolean tagPhrase) throws Exception {
		Task3Corpus task3Corpus = new Task3Corpus();
		XValidatingObjectCorpus<Chunking> tenCrossCorpus = task3Corpus.getTask3Corpus(1, 2000, cat, NUM_FOLDS, tagTarget, tagPhrase, true);
		return testCorpusIsTrain(tenCrossCorpus, tokeFac, cat, name, from, to, tran, tagTarget, tagPhrase);
	}

	public Result testCorpusIsTrain(XValidatingObjectCorpus<Chunking> corpus, int tokeFac, String cat, String name, int from, int to, boolean tran, boolean tagTarget, boolean tagPhrase)
			throws Exception {

		XValidatingObjectCorpus<Chunking> tenCrossCorpus = corpus;

		ChainCrfFeatureExtractor<String> featureExtractor = new CrfFeatureExtractor();

		boolean addIntercept = true;

		int minFeatureCount = 1;

		boolean cacheFeatures = true;

		boolean allowUnseenTransitions = true;

		double priorVariance = 4.0;
		boolean uninformativeIntercept = true;
		RegressionPrior prior = RegressionPrior.gaussian(priorVariance, uninformativeIntercept);
		int priorBlockSize = 3;

		double initialLearningRate = 0.05;
		double learningRateDecay = 0.995;
		AnnealingSchedule annealingSchedule = AnnealingSchedule.exponential(initialLearningRate, learningRateDecay);

		double minImprovement = 0.00001;
		int minEpochs = 2;
		int maxEpochs = 2000;

		Reporter reporter = Reporters.stdOut().setLevel(LogLevel.DEBUG);

		System.out.println("\nEstimating");

		long seed = 42L;
		tenCrossCorpus.permuteCorpus(new Random(seed));

		if (tokeFac == 0)
			tokenizerFactory = new IctSplitTokenizerFactory();
		else if (tokeFac == 1)
			tokenizerFactory = CharacterTokenizerFactory.INSTANCE;
		else if (tokeFac == 3) {
			tokenizerFactory = new TokenNGramTokenizerFactory(CharacterTokenizerFactory.INSTANCE, 1, 3);
		} else if (tokeFac == 2) {
			tokenizerFactory = new TokenNGramTokenizerFactory(new IctSplitTokenizerFactory(), 1, 3);
		}

		TagChunkCodec codec = new CrfBioTagChunkCodec(tokenizerFactory, true);
		String[] testSentPath = getPath(dir + name + File.separator + "test" + File.separator, "test_" + name,Math.min(NUM_FOLDS, to));

		Result result2 = new Result(name);
		for (int fold = from; fold < Math.min(NUM_FOLDS, to); ++fold) {

			tenCrossCorpus.setFold(fold);

			File modelFile = new File(getPath(dir + name, name,Math.min(NUM_FOLDS, to))[fold]);
			ChainCrfChunker crf;
			if (tran) {
				crf = ChainCrfChunker.estimate(tenCrossCorpus, codec, tokenizerFactory, featureExtractor, addIntercept, minFeatureCount, cacheFeatures, prior, priorBlockSize, annealingSchedule,
						minImprovement, minEpochs, maxEpochs, reporter);

				System.out.println("\nCompiling to file=" + modelFile);
				// AbstractExternalizable.serializeTo(crf, modelFile);
			} else {
				crf = (ChainCrfChunker) AbstractExternalizable.readObject(modelFile);

			}

			ChunkerEvaluator chunkerEvaluator = new ChunkerEvaluator(crf);
			tenCrossCorpus.visitTest(chunkerEvaluator);

			ChunkingEvaluation chunkingEvaluation = chunkerEvaluator.evaluation();
			result2.add(chunkingEvaluation.precisionRecallEvaluation());

		}

		log.error(result2.toMatricString());
		// System.out.println(result2.toString());
		// FileUtility.addWriteString("G:\\1\\result\\Result.test",
		// result2.toString());
		return result2;

	}

	public static class Result {
		public List<PrecisionRecallEvaluation> mPRList = new ArrayList<PrecisionRecallEvaluation>();
		public String name;

		public Result(String n) {
			name = n;
		}

		public List<PrecisionRecallEvaluation> getPREvaluations() {
			return mPRList;
		}

		double f1Sum;
		int num;

		public String toString() {
			String msg = "";
			num = mPRList.size();
			msg += zsd.review.common.Option.LineMark() + zsd.review.common.Option.LineMark();
			msg += "epoch = " + ChainCrf.getEpochNum();
			msg += zsd.review.common.Option.LineMark() + name + zsd.review.common.Option.LineMark() + "---------------------------------------------------------------------------" + "\r\n";
			int k = 1;
			String kstr = "" + k;
			double recSum = 0;
			double preSum = 0;
			f1Sum = 0;
			msg += "试验次数" + "\t" + "召回率" + "\t\t\t" + "准确率 " + "\t\t\t" + "F1值" + zsd.review.common.Option.LineMark();
			for (PrecisionRecallEvaluation precisionRecallEvaluation : mPRList) {
				msg += "第" + StringUtility.fillPreLength(kstr, ' ', 2) + " " + "次" + "\t" + precisionRecallEvaluation.recall() + "\t" + precisionRecallEvaluation.precision() + "\t"
						+ precisionRecallEvaluation.fMeasure() + "\r\n";
				recSum += precisionRecallEvaluation.recall();
				preSum += precisionRecallEvaluation.precision();
				f1Sum += precisionRecallEvaluation.fMeasure();
			}
			msg += "---------------------------------------------------------------------------\r\n";
			msg += "所有的" + "  " + recSum / num + "\t" + preSum / num + "\t" + f1Sum / num + "\r\n";
			msg += zsd.review.common.Option.LineMark() + zsd.review.common.Option.LineMark();
			return msg;
		}

		public double getAveF1() {
			toString();
			return f1Sum / num;
		}

		public String toMatricString() {
			List<String[]> results = new ArrayList<String[]>();

			int num = mPRList.size();

			int k = 1;
			String kstr = "" + k;
			double recSum = 0;
			double preSum = 0;
			double f1Sum = 0;
			String[] starts = { StringUtility.fillTailLength("Trial Num", ' ', 16), StringUtility.fillTailLength("Recall", ' ', 25), StringUtility.fillTailLength("Precision", ' ', 25),
					StringUtility.fillTailLength("F1", ' ', 25) };
			for (PrecisionRecallEvaluation precisionRecallEvaluation : mPRList) {
				String[] exresult = { StringUtility.fillTailLength(StringUtility.fillTailLength(kstr, ' ', 2) + "Time", ' ', 16),
						StringUtility.fillTailLength("" + precisionRecallEvaluation.recall(), ' ', 25), StringUtility.fillTailLength("" + precisionRecallEvaluation.precision(), ' ', 25),
						StringUtility.fillTailLength("" + precisionRecallEvaluation.fMeasure(), ' ', 25) };
				recSum += precisionRecallEvaluation.recall();
				preSum += precisionRecallEvaluation.precision();
				f1Sum += precisionRecallEvaluation.fMeasure();
				results.add(exresult);
			}
			String[] ends = { StringUtility.fillTailLength("Aveage", ' ', 16), StringUtility.fillTailLength("" + recSum / num, ' ', 25), StringUtility.fillTailLength("" + preSum / num, ' ', 25),
					StringUtility.fillTailLength("" + f1Sum / num, ' ', 25) };
			String msg = "";
			msg += Option.LineMark();
			msg += "epoch = " + ChainCrf.getEpochNum();
			msg += Option.LineMark() + "learningRate = " + ChainCrf.getLearningRate();
			msg += Option.LineMark() + "log2Likelihood = " + ChainCrf.getLog2Likelihood();
			msg += Option.LineMark() + "log2Prior = " + ChainCrf.getLog2Prior();
			msg += Option.LineMark() + "bestLog2LikelihoodAndPrior = " + ChainCrf.getBestLog2LikelihoodAndPrior();
			msg += Option.LineMark() + name + Option.LineMark() + StringUtility.fillTailLength("", '-', 100);
			msg += Option.LineMark() + StringUtility.arrayToStr(starts, "");
			for (int i = 0; i < results.size(); i++)
				msg += Option.LineMark() + StringUtility.arrayToStr(results.get(i), "");
			msg += Option.LineMark() + StringUtility.fillTailLength("", '-', 100);
			msg += Option.LineMark() + StringUtility.arrayToStr(ends, "");
			msg += Option.LineMark() + Option.LineMark();
			return msg;
		}

		public void add(PrecisionRecallEvaluation precisionRecallEvaluation) {
			mPRList.add(precisionRecallEvaluation);
		}

		public int compareF1(Result result, int i) {
			double f1 = getAveF1();
			double f2 = result.getAveF1();
			if (f1 > f2)
				return 1;
			else if (f1 < f2) {
				return -1;
			} else {
				return 0;
			}
		}
	}

	public static boolean[] select = CrfChunkerTest.fillArray(20, true);
	public static double[] weigth = CrfChunkerTest.fillArray(20, 1.0);

	// 在11--D上做交叉验证 ，调节特征选择
	public void testFeatureSelect(int tokFac, int N, String type) throws Exception {
		for (int i = 0; i < select.length; i++) {
			select[i] = true;
		}
		Result result1 = testIsTrain(tokFac, type, type + "_feature_select" + "_all", 0, 1, true, true, false);
		for (int i = 0; i < N; i++) {
			select[i] = false;
			log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, " "));
			Result result2 = testIsTrain(tokFac, type, type + "_feature_select_" + i + "_false", 0, 1, true, true, false);
			if (result1.compareF1(result2, 0) > 0)
				select[i] = true;
			else
				result1 = result2;
		}
		log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
	}

	// 在09上交叉验证,不过滤训练集
	public void test2009FeatureSelect(int tokFac, int N, String type, int maxNum) throws Exception {
		for (int i = 0; i < select.length; i++) {
			select[i] = true;
		}
		COAE2009TargetCorpus COAE2009TargetCorpus = new COAE2009TargetCorpus();
		XValidatingObjectCorpus<Chunking> trainCorpus = COAE2009TargetCorpus.get2009TargetCorpus(1, maxNum, NUM_FOLDS, true);

		Result result1 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_feature_select" + "_all", 0, 1, true, true, false);
		for (int i = 0; i < N; i++) {
			select[i] = false;
			log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
			Result result2 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_feature_select_" + i + "_false", 0, 1, true, true, false);
			if (result1.compareF1(result2, 0) > 0) {
				select[i] = true;
				weigth[i] += 0.5;
				Result result3 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_feature_select_" + i + "_" + weigth[i] + "_true", 0, 1, true, true, false);
				while (result3.compareF1(result1, 0) > 0) {
					log.error(Option.LineMark() + "Weigth = " + StringUtility.arrayToStr(weigth, ","));
					result1 = result3;
					result3 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_feature_select_" + i + "_" + weigth[i] + "_true", 0, 1, true, true, false);
					weigth[i] += 0.5;
				}
			} else
				result1 = result2;
		}
		log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
		log.error(Option.LineMark() + "Weigth = " + StringUtility.arrayToStr(weigth, " "));
	}

	// 在09上交叉验证，与全体的11做字符的相似性过滤
	public void test2009_FilterFeatureSelect(int tokFac, int N, String type, int maxNum) throws Exception {
		for (int i = 0; i < select.length; i++) {
			select[i] = true;
		}
		COAE2009TargetCorpus COAE2009TargetCorpus = new COAE2009TargetCorpus();
		XValidatingObjectCorpus<Chunking> trainCorpus = COAE2009TargetCorpus.get2009TargetCorpus(1, 10000, NUM_FOLDS, true);
		Task3Corpus testTask3Corpus = new Task3Corpus();
		TrainCorpusFilter trainCorpusFilter = new TrainCorpusFilter();

		XValidatingObjectCorpus<Chunking> test = testTask3Corpus.getTask3AllCorpus(1, 10, true, false, true);
		trainCorpusFilter.setTokenizerFactory(trainFactory);
		trainCorpus = trainCorpusFilter.getFilterCorpus(maxNum, trainCorpus, test);

		Result result1 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_filter_feature_select" + "_all", 0, 1, true, true, false);
		for (int i = 0; i < N; i++) {
			select[i] = false;
			log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
			Result result2 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_filter_feature_select_" + i + "_false", 0, 1, true, true, false);
			if (result1.compareF1(result2, 0) > 0) {
				select[i] = true;
				weigth[i] += 0.5;
				Result result3 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_filter_feature_select_" + i + "_" + weigth[i] + "_true", 0, 1, true, true, false);
				while (result3.compareF1(result1, 0) > 0) {
					log.error(Option.LineMark() + "Weigth = " + StringUtility.arrayToStr(weigth, ","));
					result1 = result3;
					result3 = testCorpusIsTrain(trainCorpus, tokFac, type, type + "_filter_feature_select_" + i + "_" + weigth[i] + "_true", 0, 1, true, true, false);
					weigth[i] += 0.5;
				}
			} else
				result1 = result2;
		}
		log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
		log.error(Option.LineMark() + "Weigth = " + StringUtility.arrayToStr(weigth, " "));
	}

	public static boolean[] fillArray(int num, boolean b) {
		boolean[] a = new boolean[num];
		for (int i = 0; i < a.length; i++)
			a[i] = b;
		return a;
	}

	public static double[] fillArray(int num, double b) {
		double[] a = new double[num];
		for (int i = 0; i < a.length; i++)
			a[i] = b;
		return a;
	}

	public boolean[] getSelect() {
		return select;
	}

	public static void setSelect(boolean[] s) {
		for (int i = 0; i < s.length; i++) {
			select[i] = s[i];
		}
	}

	public void testAll(int tokFac) throws Exception {
		CrfChunkerTest chunkerTest = new CrfChunkerTest();
		// chunkerTest.testIsTrain("D", "D_target", 0, 1, true, true, false);
		// chunkerTest.testIsTrain("D", "D_target_phrase", 0, 1, true, true, true);
		// chunkerTest.testIsTrain("D", "D_phrase", 0, 1, true, false, true);
		boolean[] s = { true, true, false, false, false, true, false, false, false, true, false, false, true, false, true };
		CrfChunkerTest.setSelect(s);
		chunkerTest.testIsTrain(tokFac, "E", "E_target", 0, 1, true, true, false);
		// chunkerTest.testIsTrain("E", "E_target_phrase", 0, 1, false, true, true);
		// chunkerTest.testIsTrain("E", "E_phrase", 0, 1, true, false, true);
		// chunkerTest.testIsTrain("F", "F_target", 0, 1, true, true, false);
		// chunkerTest.testIsTrain("F", "F_target", 0, 1, false, true, false);
		// chunkerTest.testIsTrain("F", "F_target_phrase", 0, 1, false, true, true);
		// chunkerTest.testIsTrain("F", "F_phrase", 0, 1, true, false, true);
	}

	// 09做训练，11做测试，按照字符相似性排序，
	public Result test2009Train(boolean filter, int num, int testType, String name, boolean train, int trainFac, int tokeFac) throws Exception {
		setFilterTokenFac(trainFac);

		Result result = new Result(name);
		switch (testType) {
		case 0:
			// 此时得到是与整个11测试集相似的训练集
			result = testCorpusUse2009Train("D", filter, num, 0, name + "_all", true, 0);
			break;
		case 1:
			// 此时得到是与11 D相似的训练集
			result = testCorpusUse2009Train("D", filter, num, 1, name + "_D", true, 0);
			break;
		case 2:
			// 此时得到是与11 E相似的训练集
			result = testCorpusUse2009Train("E", filter, num, 1, name + "_E", true, 0);
			break;
		case 3:
			// 此时得到是与11 F相似的训练集
			result = testCorpusUse2009Train("F", filter, num, 1, name + "_F", true, 0);
			break;
		default:
			break;
		}
		return result;
	}

	// 09做测试，11 做训练，指定与测试集相似的类型：type+ testType
	public Result testCorpusUse2009Train(String testType, boolean filter, int num, int type, String name, boolean train, int tokeFac) throws Exception {
		COAE2009TargetCorpus COAE2009TargetCorpus = new COAE2009TargetCorpus();
		XValidatingObjectCorpus<Chunking> trainCorpus = COAE2009TargetCorpus.get2009TargetCorpus(1, 10000, 0, true);
		Task3Corpus testTask3Corpus = new Task3Corpus();
		TrainCorpusFilter trainCorpusFilter = new TrainCorpusFilter();
		XValidatingObjectCorpus<Chunking> test;
		trainCorpusFilter.setTokenizerFactory(trainFactory);
		if (filter) {
			switch (type) {
			case 0:
				test = testTask3Corpus.getTask3AllCorpus(1, 10, true, false, true);
				trainCorpus = trainCorpusFilter.getFilterCorpus(num, trainCorpus, test);
				break;
			default:
				test = testTask3Corpus.getTask3Corpus(1, 7000, testType, 10, true, false, true);
				trainCorpus = trainCorpusFilter.getFilterCorpus(num, trainCorpus, test);
				break;
			}

		}
		ChainCrfFeatureExtractor<String> featureExtractor = new CrfFeatureExtractor();

		boolean addIntercept = true;

		int minFeatureCount = 1;

		boolean cacheFeatures = true;

		boolean allowUnseenTransitions = true;

		double priorVariance = 4.0;
		boolean uninformativeIntercept = true;
		RegressionPrior prior = RegressionPrior.gaussian(priorVariance, uninformativeIntercept);
		int priorBlockSize = 3;

		double initialLearningRate = 0.05;
		double learningRateDecay = 0.995;
		AnnealingSchedule annealingSchedule = AnnealingSchedule.exponential(initialLearningRate, learningRateDecay);

		double minImprovement = 0.00001;
		int minEpochs = 2;
		int maxEpochs = 2000;

		Reporter reporter = Reporters.stdOut().setLevel(LogLevel.DEBUG);

		System.out.println("\nEstimating");

		setFeatureTokenFac(tokeFac);

		TagChunkCodec codec = new CrfBioTagChunkCodec(tokenizerFactory, true);
		String[] testSentPath = getPath(dir + name + "\\test\\", "test_" + name,1);

		File modelFile = new File(getPath(dir + name, name,1)[0]);
		ChainCrfChunker crf;
		if (train) {
			crf = ChainCrfChunker.estimate(trainCorpus, codec, tokenizerFactory, featureExtractor, addIntercept, minFeatureCount, cacheFeatures, prior, priorBlockSize, annealingSchedule, minImprovement,
					minEpochs, maxEpochs, reporter);

			System.out.println("\nCompiling to file=" + modelFile);
			// AbstractExternalizable.serializeTo(crf, modelFile);
		} else {
			crf = (ChainCrfChunker) AbstractExternalizable.readObject(modelFile);
		}
		Result result2 = new Result(name);
		Task3Corpus task3Corpus = new Task3Corpus();
		XValidatingObjectCorpus<Chunking> testCorpus1 = task3Corpus.getTask3Corpus(1, 10000, "D", 1, true, false, true);
		XValidatingObjectCorpus<Chunking> testCorpus2 = task3Corpus.getTask3Corpus(1, 10000, "E", 1, true, false, true);
		XValidatingObjectCorpus<Chunking> testCorpus3 = task3Corpus.getTask3Corpus(1, 10000, "F", 1, true, false, true);
		ChunkerEvaluator chunkerEvaluator = new ChunkerEvaluator(crf);

		testCorpus1.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation.precisionRecallEvaluation());

		testCorpus2.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation2 = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation2.precisionRecallEvaluation());

		testCorpus3.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation3 = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation3.precisionRecallEvaluation());

		log.error(result2.toMatricString());

		return result2;

	}

	public void setFeatureTokenFac(int n) {
		switch (n) {
		case 0:
			tokenizerFactory = new IctSplitTokenizerFactory();
			break;
		case 1:
			tokenizerFactory = CharacterTokenizerFactory.INSTANCE;
			break;
		case 2:
			tokenizerFactory = new TokenNGramTokenizerFactory(CharacterTokenizerFactory.INSTANCE, 1, 3);
			break;
		case 3:
			tokenizerFactory = new TokenNGramTokenizerFactory(new IctSplitTokenizerFactory(), 1, 3);
			break;
		default:
			tokenizerFactory = new IctSplitTokenizerFactory();
			break;
		}
	}

	public void setFilterTokenFac(int n) {
		switch (n) {
		case 0:
			trainFactory = CharacterTokenizerFactory.INSTANCE;
			break;
		case 1:
			trainFactory = new IctSplitTokenizerFactory();
			break;
		case 2:
			trainFactory = new TokenNGramTokenizerFactory(CharacterTokenizerFactory.INSTANCE, 1, 3);
			break;
		case 3:
			trainFactory = new TokenNGramTokenizerFactory(new IctSplitTokenizerFactory(), 1, 3);
			break;
		default:
			trainFactory = CharacterTokenizerFactory.INSTANCE;
			break;
		}
	}

	// 09训练，11测试，指定训练集
	public Result testResultUseTran(String name, boolean train, int filtTokenFac, int tokeFac, XValidatingObjectCorpus<Chunking> trainCorpus, int split) throws Exception {
		ChainCrfFeatureExtractor<String> featureExtractor = new CrfFeatureExtractor();

		boolean addIntercept = true;

		int minFeatureCount = 1;

		boolean cacheFeatures = true;

		boolean allowUnseenTransitions = true;

		double priorVariance = 4.0;
		boolean uninformativeIntercept = true;
		RegressionPrior prior = RegressionPrior.gaussian(priorVariance, uninformativeIntercept);
		int priorBlockSize = 3;

		double initialLearningRate = 0.05;
		double learningRateDecay = 0.995;
		AnnealingSchedule annealingSchedule = AnnealingSchedule.exponential(initialLearningRate, learningRateDecay);

		double minImprovement = 0.00001;
		int minEpochs = 2;
		int maxEpochs = 2000;

		Reporter reporter = Reporters.stdOut().setLevel(LogLevel.DEBUG);

		System.out.println("\nEstimating");

		setFeatureTokenFac(tokeFac);

		TagChunkCodec codec = new CrfBioTagChunkCodec(tokenizerFactory, true);
		String[] testSentPath;
		testSentPath = getPath(dir + name + File.separator +"test" + File.separator, "test_" + name,1);

		File modelFile = new File(getPath( dir + name, name,1)[0]);
		ChainCrfChunker crf;
		if (train) {
			crf = ChainCrfChunker.estimate(trainCorpus, codec, tokenizerFactory, featureExtractor, addIntercept, minFeatureCount, cacheFeatures, prior, priorBlockSize, annealingSchedule, minImprovement,
					minEpochs, maxEpochs, reporter);

			System.out.println("\nCompiling to file=" + modelFile);
			AbstractExternalizable.serializeTo(crf, modelFile);
		} else {
			crf = (ChainCrfChunker) AbstractExternalizable.readObject(modelFile);
		}
		Result result2 = new Result(name);
		Task3Corpus task3Corpus = new Task3Corpus();
		int folds = 1;
		XValidatingObjectCorpus<Chunking> testCorpus1 = task3Corpus.getTask3Corpus(1, 10000, "D", folds, true, false, true);
		XValidatingObjectCorpus<Chunking> testCorpus2 = task3Corpus.getTask3Corpus(1, 10000, "E", folds, true, false, true);
		XValidatingObjectCorpus<Chunking> testCorpus3 = task3Corpus.getTask3Corpus(1, 10000, "F", folds, true, false, true);
		ChunkerEvaluator chunkerEvaluator = new ChunkerEvaluator(crf);

		testCorpus1.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation.precisionRecallEvaluation());

		testCorpus2.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation2 = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation2.precisionRecallEvaluation());

		testCorpus3.visitTest(chunkerEvaluator);
		ChunkingEvaluation chunkingEvaluation3 = chunkerEvaluator.evaluation();
		result2.add(chunkingEvaluation3.precisionRecallEvaluation());

		log.error(result2.toMatricString());

		return result2;
	}

	// 09训练，11 测试 ，按照与11—— D 字符相似性过滤训练集，
	public void test2009_2011FeatureSelect(int N, String name, int maxNum09) throws Exception {
		for (int i = 0; i < select.length; i++) {
			select[i] = true;
		}
		COAE2009TargetCorpus COAE2009TargetCorpus = new COAE2009TargetCorpus();
		XValidatingObjectCorpus<Chunking> trainCorpus = COAE2009TargetCorpus.get2009TargetCorpus(1, maxNum09, NUM_FOLDS, true);

		Result result1 = test2009Train(true, 3000, 1, name + "09_11_fiter" + "all_false", false, 0, 0);
		for (int i = 0; i < N; i++) {
			select[i] = false;
			log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
			Result result2 = test2009Train(true, 3000, 1, name + "09_11_fiter_" + i + "_false", true, 0, 0);
			if (result1.compareF1(result2, 0) > 0) {
				select[i] = true;
				weigth[i] += 1.0;
				Result result3 = test2009Train(true, 3000, 1, name + "_feature_select_" + i + "_" + weigth[i] + "_true", true, 0, 0);
				while (result3.compareF1(result1, 0) > 0) {
					log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(weigth, ","));
					result1 = result3;
					result3 = test2009Train(true, 3000, 1, name + "_feature_select_" + i + "_" + weigth[i] + "_true", true, 0, 0);
					weigth[i] += 1.0;
				}
			} else
				result1 = result2;
		}
		log.error(Option.LineMark() + "Select = " + StringUtility.arrayToStr(select, ","));
		log.error(Option.LineMark() + "Weigth = " + StringUtility.arrayToStr(weigth, ","));
	}

	// 09训练，11 测试，基于图的训练集排序
	public void test09_11GraphRank(int graph, boolean update, int split, int type, int testNum, double alph, double alph2, double beita, double gama) throws Exception {
		COAE2009TargetCorpus COAE2009TargetCorpus = new COAE2009TargetCorpus();
		XValidatingObjectCorpus<Chunking> trainCorpus = COAE2009TargetCorpus.get2009TargetCorpus(split, 10000, 0, true);
		// ListCorpus<Chunking> listTran = CrfCorpus.xtoListCorpus(trainCorpus);
		Task3Corpus testTask3Corpus = new Task3Corpus();
		// TrainCorpusFilter trainCorpusFilter = new TrainCorpusFilter();
		XValidatingObjectCorpus<Chunking> test;
		// trainCorpusFilter.setTokenizerFactory(trainFactory);
		// test = testTask3Corpus.getTask3AllCorpus(split,10, true, false, true);
		test = testTask3Corpus.getTask3Corpus(split, 10000, "D", 0, true, false, true);
		GraphRank graphRank = new GraphRank();
		graphRank.alph2 = alph2;
		boolean updateFilter = false;
		trainCorpus = graphRank.getRankedCorpus(graph, "test_0_1_2", type, testNum, alph, beita, gama, trainCorpus, test, 3, updateFilter, split);
		// trainCorpus = trainCorpusFilter.FilterCorpus("test_0_1",type,testNum,
		// alph, beita, gama, trainCorpus, test,3,false,split);

		testResultUseTran(graph + "_Graph_" + testNum + "_" + split + "_graph_filter_" + alph + "_" + alph2 + "_" + beita + "_" + gama, update, 0, 0, trainCorpus, split);
	}

	// 09训练，11 测试，基于图的训练集排序,调剂参数
	public void test09_11GraphRank() throws Exception {
		// double sim = alph * toksim + (1 - alph) * featsim;
		weigth[0] = 2.0;
		int graph = 0;
		boolean update = true;
		int split = 1;
		int type = -1;
		int testNum = 5000;
		double alph = 1;
		double beita = 0.9;
		double gama = 0.9;
		double alph2 = 0;
		split = 20;
		testNum = 5000;
		alph = 0.5;
		graph = 2;
		// test09_11GraphRank(
		// graph,update,split,type,5000,alph,beita,gama);//全部的训练集

		// test09_11GraphRank(
		// graph,update,split,type,testNum,alph,beita,gama);//非图排序的
		alph = 0.3;
		alph2 = 0.8;
		beita = 0.9;
		gama = 0.5;
		test09_11GraphRank(graph, update, split, type, 5000, alph, alph2, beita, gama);// 全部的训练集
		beita = 0.9;
		gama = 0.6;
		test09_11GraphRank(graph, update, split, type, 5000, alph, alph2, beita, gama);// 全部的训练集
		// alph = 0.2;
		beita = 0.9;
		gama = 0.7;
		test09_11GraphRank(graph, update, split, type, 5000, alph, alph2, beita, gama);// 全部的训练集
		// alph = 0.1;
		beita = 0.9;
		gama = 0.8;
		test09_11GraphRank(graph, update, split, type, 5000, alph, alph2, beita, gama);// 全部的训练集
		alph = 1;
		// test09_11GraphRank(
		// graph,update,split,type,5000,alph,beita,gama);//全部的训练集
		graph = 1;
		// test09_11GraphRank(
		// graph,update,split,type,testNum,alph,beita,gama);//图排序
		alph = 0.5;
		// test09_11GraphRank(
		// graph,update,split,type,testNum,alph,beita,gama);//非图排序的

		// alph = 1;
		graph = 0;
		// test09_11GraphRank( graph,update,split,type,testNum,alph,beita,gama);//非图
		graph = 2;// 随即
		// test09_11GraphRank(graph, update, split, type, testNum, alph, beita,
		// gama);// 非图排序的
		graph = 3;// 初始向量1，图排
		// test09_11GraphRank(graph, update, split, type, testNum, alph, beita,
		// gama);// 图排序
		graph = 1;// 初始向量相似性
		// test09_11GraphRank(graph, update, split, type, testNum, alph, beita,
		// gama);// 图排序
		/*
		 * test09_11GraphRank(false,true,1,0,3000, 1, 0.9, 0.9);
		 * test09_11GraphRank(true,true,1,0,3000, 1, 0.9, 0.9);
		 * test09_11GraphRank(false,true,1,0,5000, 1, 0.9, 0.9);
		 */
		// test09_11GraphRank("1000_2",true,2,0,1000, 0.3, 0.9, 0.9);
		// test09_11GraphRank("500graph_rank",true,1,0,3000, 0.4, 0.9, 0.9);
		// test09_11GraphRank(1,0,3000, 1, 0.9, 0.9);
		// test09_11GraphRank(5,0,3000, 1, 0.9, 0.9);
		// test09_11GraphRank("500graph_rank",true,5,0,500, 1, 0.9, 0.9);
		// test09_11GraphRank("3000",true,5,0,3000, 0.5, 0.9, 0.9);
		// test09_11GraphRank("4000_2",true,2,0,4000, 0.3, 0.9, 0.9);
		// test09_11GraphRank("1000_2",true,2,0,1000, 0.5, 0.9, 0.9);
		// test09_11GraphRank("NOtGraph_1000_2",true,2,0,1000, 1, 0.9, 0.9);
		// test09_11GraphRank(false,"NOt_Graph_1000_5",true,5,0,1000, 0.5, 0.9,
		// 0.9);
		// test09_11GraphRank(true,"Graph_1000_5",true,5,0,1000, 0.5, 0.9, 0.9);
	}

	// 2009训练，2011做测试，按照字符相似性过滤训练集，调节与训练做相似性的测试集，以及过滤用的分词工厂
	public static void test2009All() throws Exception {
		CrfChunkerTest chunkerTest = new CrfChunkerTest();
		// Result test2009Train(boolean filter, int num, int testType, String name,
		// boolean train, int trainFac, int tokeFac)

		// 以全体11做相似性度量,
		/*
		 * chunkerTest.test2009Train(true, 3000, 0, "09_fiter_D0", true, 0, 0);//
		 * 字符分词工厂 chunkerTest.test2009Train(true, 3000, 0, "09_fiter_D1", true, 1,
		 * 0); chunkerTest.test2009Train(true, 3000, 0, "09_fiter_D2", true, 2, 0);
		 * chunkerTest.test2009Train(true, 3000, 0, "09_fiter_D3", true, 3, 0);
		 */

		// //以全体11--D做相似性度量
		chunkerTest.test2009Train(true, 3000, 1, "09_fiter_D0", true, 0, 0);
		chunkerTest.test2009Train(true, 3000, 1, "09_fiter_D1", true, 1, 0);
		chunkerTest.test2009Train(true, 3000, 1, "09_fiter_D2", true, 2, 0);
		chunkerTest.test2009Train(true, 3000, 1, "09_fiter_D3", true, 3, 0);

		chunkerTest.test2009Train(true, 3000, 2, "09_fiter_E0", true, 0, 0);
		chunkerTest.test2009Train(true, 3000, 2, "09_fiter_E1", true, 1, 0);
		chunkerTest.test2009Train(true, 3000, 2, "09_fiter_E2", true, 2, 0);
		chunkerTest.test2009Train(true, 3000, 2, "09_fiter_E3", true, 3, 0);

		chunkerTest.test2009Train(true, 3000, 3, "09_fiter_F0", true, 0, 0);
		chunkerTest.test2009Train(true, 3000, 3, "09_fiter_F1", true, 1, 0);
		chunkerTest.test2009Train(true, 3000, 3, "09_fiter_F2", true, 2, 0);
		chunkerTest.test2009Train(true, 3000, 3, "09_fiter_F3", true, 3, 0);

	}

	public static void main(String[] args) throws Exception {
		CrfChunkerTest chunkerTest = new CrfChunkerTest();
		// chunkerTest.testIsTrain(3,"F","F_T_3", 0, 1, true, true, false);
		// chunkerTest.testAll();

		// chunkerTest.testFeatureSelect(14, "E");
		// chunkerTest.test2009FeatureSelect(0, 14, "x2009", 7000);
		// chunkerTest.testCorpusUse2009Train("D", false, 2000, 0, "09_all", true,
		// 0);
		// chunkerTest.test2009Train(true, 3000, 0, "09_fiter", true, 1, 0);
		// chunkerTest.test2009_2011FeatureSelect(14, "ALL", 7000);
		chunkerTest.test09_11GraphRank();
		// test2009All();
	}

	public TokenizerFactory getTrainFactory() {
		return trainFactory;
	}

	public void setTrainFactory(TokenizerFactory trainFactory) {
		this.trainFactory = trainFactory;
	}

	public static double[] getWeigth() {
		return weigth;
	}

	public static void setWeigth(double[] weigth) {
		CrfChunkerTest.weigth = weigth;
	}

}
